#include <stdlib.h>
#include <time.h>
#include <string.h>
#include "../../../mac/mac.h"

/* for debug only */
static int8 sml_ed_val = 0x80;
static rf_pan_id = 0x00;

static uint8 tx_frame[128] = {0};
static uint8 frm_len = 0;


/*! initialize the rf.
 *  @return return the status of the radio.
 */
int8 rf_init(void)
{
    /* tentative method */
    sml_ed_val = 0x80;
    rf_disable_addr_recg();
    /* short_addr and pan_id info don't need to be initialized */
    rf_clr_pan_coord();
}

int8 rf_reset(void)
{
    /* return cc2420_reset(); */
}

/*! start transmiting. This interface is not used at present.
 *  @return the status of radio.
 */
uint8 rf_tx_on(void)
{
    //return cc2420_command(CC2420_STXON);
}

/*! send if the chanel is clear.
 *  @return if the frame is transmitted, return 1 if transmitted,
 *          else return 0.
 */
bool rf_tx_cca_on(void)
{
    return true;
}

/*! write frame radio tx fifo.
 *  @param buf pointer to the frame to be wrote.
 *  @param count number of bytes of the frame.
 *  @return the status of the radio.
 */
int8 rf_write_tx_fifo(uint8 *buf, uint8 len)
{
    if (len == 0) {
        frm_len = 0;
        return MAC_OK;
    }

    if (len > ((127+1))) {
        return MAC_FRAME_TOO_LONG;
    }

    memset(tx_frame, 0, sizeof(tx_frame));
    memcpy(tx_frame, buf, len);
    frm_len = len;

    return MAC_OK;
}

/*! read frame from the rx fifo.
 *  @param buf pointer to the place to place the frame.
 *  @param count the number of bytes of the frame in the rx fifo.
 *  @return the status of the radio.
 */
int8 rf_read_rx_fifo(uint8 *buf, uint8 len)
{
    /* return cc2420_read_fifo(buf, count); */
}

/*! flush tx_fifo, after flush.
 *  @return the status of the rf.
 */
int8 rf_flush_tx_fifo(void)
{
    /* return cc2420_command(CC2420_FLUSHTX); */
}

/*! flush rx fifo.
 *  @return the status of the rf.
 */
int8 rf_flush_rx_fifo(void)
{
#if 0
    uint8 buf[2];
    /* words from the 802.15.4 spec:
     * "Flush the RX FIFO buffer and reset the demodulator. Always read at least
     * one byte from the RXFIFO before issuing the SFLUSHRX command strobe"
     */
    rf_read_rx_fifo(buf, 2);

    return cc2420_command(CC2420_FLUSHRX);
#endif
}

/*! set short address for address recognition.
 *  @return the status of the rf.
 */
uint16 rf_set_short_addr(uint16 short_addr)
{
    /* return cc2420_write_ram(CC2420_RAM_SHORTADR, 2, short_addr); */
}

/*! set pan id for address recognition.
 *  @param pan_id
 *  @return teh status of the rf.
 */
uint16 rf_set_pan_id(uint16 pan_id)
{
    /* return cc2420_write_ram(CC2420_RAM_PANID, 2, pan_id); */
    rf_pan_id = pan_id;
}

/*! get pan id for address recognition.
 *  @param pan_id
 *  @return teh status of the rf.
 */
uint16 rf_get_pan_id(void)
{
    return rf_pan_id;
    /* return cc2420_write_ram(CC2420_RAM_PANID, 2, pan_id); */
}

/*! set the ieee extended address.
 *  @param ieee_addr.
 *  @return the status of the rf.
 */
uint64 rf_set_ieee_addr(uint64 ieee_addr)
{
    /* return cc2420_write_ram(CC2420_RAM_IEEEADR, 8, ieee_addr); */
}


int8 rf_set_current_chnl(uint8 chnl)
{

}

int8 rf_set_current_page(uint8 page)
{

}

/*! call the redio driver to start the energy scan.
 *  @return the energy value, which is signed on two's complement.
 */
int8 rf_ed_scan(void)
{
    int8 r;

    //srand(time(NULL));
    r = rand() % 0xff;
    MAC_DEBUG("rf_ed_scan: %d\n", r);

    if (r > sml_ed_val) {
        sml_ed_val = r;
    }
    return r;
}

uint8 rf_set_chnl(uint8 chnl)
{
/* call the radio driver to set the channel. */
}

uint8  rf_get_chnl(void)
{
/* call the radio driver to set the channel. */
}

/* empty */
uint8  rf_set_chnl_page(uint8 chnl_page)
{

}

/* for debug only */
int8 rf_get_sml_ed_val(void)
{
    return sml_ed_val;
}

/* receiving interrupt server routine */
int8 rf_recv_isr(void)
{
    buf_t *buf;
    uint8 len;
    uint16 link_quality;
    uint16 *plq;

    buf = buf_alloc(true);
    if (buf == NULL) {
        return MAC_ERR;
    }

    /* get frame length field */
    rf_read_rx_fifo(&len, 1);
    if (len > 127) {
        return MAC_ERR;
    }
    /* left move the buf pointer to the right place */
    buf->length = len;
    buf->ptr -= (len-1);
    rf_read_rx_fifo(buf->ptr, len);
    mac_queue_push(buf);
    /* tentative: signal MAC that frame is received */
    mac_set_frm_recvd();
    
    return MAC_OK;
}

int8 rf_enable_addr_recg(void)
{
}

int8 rf_disable_addr_recg(void)
{

}

int8 rf_set_pan_coord(void)
{
}

int8 rf_clr_pan_coord(void)
{
}

uint8 rf_get_rand(void)
{
    return (rand() % 0xff);
}

bool rf_is_chnl_busy(void)
{
    static uint8 i = 0;

    if (i == 0) {
        i++;
        return true;
    } else {
        return false;
    }
}

bool rf_cca_tx(uint8 *buf, uint8 len)
{
    rf_tx(buf, len);
    return true;
}

/*
int8 rf_tx(uint8 *buf, uint8 len)
{
    if (len== 0) {
        frm_len = 0;
        return MAC_OK;
    }

    if (len> ((127+1)-2)) {
        return MAC_FRAME_TOO_LONG;
    }

    memset(tx_frame, 0, sizeof(tx_frame));
    memcpy(tx_frame, buf, len);
    frm_len = len;

    return MAC_OK;
}
*/

uint8 *get_tx_frm(void)
{
    if (tx_frame == NULL) {
        return NULL;
    }

    return tx_frame;
}

uint8 set_tx_frm_len(uint8 len)
{
    frm_len = len;

    return MAC_OK;
}

uint8 get_tx_frm_len(void)
{
    return frm_len;
}


